#include "bsf.h"
#include "bsf_interface.h"
#include "bsf_debug.h"

#pragma pack(1)

typedef struct
{
    unsigned char version;
    unsigned char ID[2];
    unsigned char match;
    unsigned char reserved[4];
} BSF_Storage;

typedef struct
{
    unsigned char len;     //包长度，不含len 即最长63
    unsigned char ID[2];   //设备ID 2
    unsigned char tag;     //标志位 1
    unsigned char buf[60]; //有效载荷 60
} BSF_Payload;

typedef struct
{
    unsigned short int RecvSendTimestamp; //以毫秒
    unsigned short int LossTimestamp;     //以毫秒计数的时间戳
    unsigned char BurnOutTimestampSec;    //以秒计数的时间戳
    unsigned char SyncTimestampSec;
    unsigned char SyncOnBootJobSec; //在上电时，会等待5秒左右匹配从机，如果没有，则会回到已匹配状态
} BSF_Timer;

typedef struct
{
    unsigned char index;
    const unsigned char *table;
} BSF_ChannelManager;
#pragma pack()

#define BSF_IS_ID_ZERO(x) (((x).ID[0] == 0x00) && ((x).ID[1] == 0x00))
#define BSF_IS_ID_MATCH(a, b) (((a).ID[0] == (b).ID[0]) && ((a).ID[1] == (b).ID[1]))
#define BSF_SET_ID_INT(x, val)                 \
    do                                         \
    {                                          \
        unsigned short int d = val;            \
        (x).ID[0] = (unsigned char)((d) >> 8); \
        (x).ID[1] = (unsigned char)(d);        \
    } while (0)
#define BSF_SET_ID_CPY(dest, src)   \
    do                              \
    {                               \
        (dest).ID[0] = (src).ID[0]; \
        (dest).ID[1] = (src).ID[1]; \
    } while (0)

#define BSF_TYPE(x) ((unsigned char)((x).tag & 0xC0))
#define BSF_TYPE_SET(x, btype) \
    do                         \
    {                          \
        (x).tag &= 0x3F;       \
        (x).tag |= btype;      \
    } while (0)
#define BSF_TYPE_EMPTY_PACK 0x00
#define BSF_TYPE_PAYLOAD_RET 0x40
#define BSF_TYPE_PAYLOAD_NORET 0x80
#define BSF_TYPE_SYNC_PACK 0xC0

#define BSF_BURNOUT_MAX 0x3F
#define BSF_BURNOUT_REFILL(x) (((x).tag) |= BSF_BURNOUT_MAX)
#define BSF_BURNOUT(x) (((x).tag) & BSF_BURNOUT_MAX)
#define BSF_BURNOUTSET(x, value)   \
    do                             \
    {                              \
        (x).tag &= 0xC0;           \
        (x).tag |= (value & 0x3F); \
    } while (0)
#define BSF_RESET_TIMER(timer, target) ((timer).target) = 0
#define BSF_SET_TIMER(timer, target, val) ((timer).target) = (val)
#define BSF_TRUE 1
#define BSF_FALSE 0
#define BSF_MATCH 0xAA

#if RECEIVER
BSF_Payload RecvPayload; //接收缓存
BSF_Payload SendPayload; //发送缓存
BSF_Payload IntlPayload;
BSF_Storage StorageInfo; //存储在RAM中的信息
BSF_ChannelManager ChannelManager;
BSF_Timer Timer;
BSF_BIT IsConnectLost = 1;
BSF_BIT TimerEnable = BSF_FALSE;
BSF_BIT MatchOnBoot = BSF_FALSE;
unsigned short int aliveCount = 0;
unsigned char isAlive = 0;
//unsigned char LocalBurnOut = BSF_BURNOUT_MAX;//计数器，用于计数本时的连续计数值
unsigned char ii = 0;
unsigned short int lii = 0;
unsigned char bsf_isMatch(void)
{
    return StorageInfo.match;
}
void bsf_init(void)
{

    bsf_itf_init();
    ChannelManager.index = 0;
    ChannelManager.table = (unsigned char *)channelTable;

    for (ii = 0; ii < sizeof(BSF_Payload); ii++)
    {
        ((unsigned char *)&RecvPayload)[ii] = 0;
        ((unsigned char *)&SendPayload)[ii] = 0;
        ((unsigned char *)&IntlPayload)[ii] = 0;
    }

    //重置TAG中，老化标志位
    BSF_BURNOUT_REFILL(RecvPayload);
    BSF_BURNOUT_REFILL(SendPayload);
    BSF_BURNOUT_REFILL(IntlPayload);

    //读取存在flash中的版本号，做好版本匹配
    bsf_itf_read(0, sizeof(BSF_Storage), (unsigned char *)&StorageInfo);
    if (StorageInfo.version != BSF_VERSION)
    {
        for (ii = 0; ii < sizeof(BSF_Storage); ii++)
        {
            ((unsigned char *)&StorageInfo)[ii] = 0;
        }

        //StorageInfo.ID = (uint16_t)DBGMCU->IDCODE;//stm32F030使用芯片的UUID低16位作为UUID//
        BSF_SET_ID_INT(StorageInfo, (unsigned short int)bsf_itf_getUID(););
        StorageInfo.version = BSF_VERSION;
    }
    TimerEnable = BSF_TRUE;
    MatchOnBoot = BSF_TRUE;
    BSF_SET_TIMER(Timer, SyncOnBootJobSec, MATCH_BOOT_TIMEOUT);
    bsf_itf_setChn(0);
    bsf_itf_setToRx();
}

/*
* 用以判断双方ID是否相同
*/
unsigned char bsf_isIdMatch()
{
    //ID不同时，以本地为主
    //if (StorageInfo.ID == IntlPayload.ID || IntlPayload.ID == 0x0000)
    if (BSF_IS_ID_MATCH(StorageInfo, IntlPayload) || BSF_IS_ID_ZERO(IntlPayload))
    {
        return BSF_TRUE;
    }
    else
    {
        return BSF_FALSE;
    }
}

/*
* 看看是不是来的包老化信息更新一些
*/
unsigned char bsf_isRecvPaloadNewer()
{
    if (BSF_BURNOUT(IntlPayload) > Timer.BurnOutTimestampSec)
    {
        return BSF_TRUE;
    }
    else
    {
        return BSF_FALSE;
    }
}

void bsf_setNextChannel()
{
    ChannelManager.index += 1;
    if (ChannelManager.index > MAX_CHANNEL_NUM)
    {
        ChannelManager.index = 0;
    }
    bsf_itf_setChn(ChannelManager.table[ChannelManager.index]);
}

void bsf_sendPack()
{
    if (SendPayload.len == 0)
    {
        IntlPayload.len = 3;
        //IntlPayload.ID = StorageInfo.ID;
        BSF_SET_ID_CPY(IntlPayload, StorageInfo);
        BSF_TYPE_SET(IntlPayload, BSF_TYPE_EMPTY_PACK);
        BSF_BURNOUTSET(IntlPayload, Timer.BurnOutTimestampSec);
        bsf_itf_send(((unsigned char *)&IntlPayload) + 1, IntlPayload.len);
    }
    else
    {
        //SendPayload.ID = StorageInfo.ID;
        BSF_SET_ID_CPY(SendPayload, StorageInfo);
        BSF_TYPE_SET(SendPayload, BSF_TYPE_PAYLOAD_NORET);
        BSF_BURNOUTSET(SendPayload, Timer.BurnOutTimestampSec);
        bsf_itf_send(((unsigned char *)&SendPayload) + 1, SendPayload.len);
        SendPayload.len = 0;
    }
}

BSF_BIT isOriginSync = BSF_TRUE;
BSF_BIT isCountDownResetEnable = BSF_FALSE;

/*阶段1通道匹配*/
/*交换ID，发射机接收机设备均会在初始化阶段固定在通道0，此时发射机持续发射ID,接收机持续回复响应,此时接收机和发射机都可以知道对方收到了自己的包,之后双方切换syncword*/
/*具体逻辑：发射机发射一个只包含头的包，包类型为空包，ID = 0x0000 ，
接收机收到0x0000后，回复有效的UUID,包类型为空包。
发射机收到有效的UUID后发送包，包类型为空包。
接收机收到有效的UUID包后，发送有UUID的空包,接收机退出匹配状态，开始使用新的syncword。
发射机如果一直(5秒)未收到接收机的匹配完成后的空包，重新设置为syncword=0x0000
发射机到空包后，退出匹配状态，开始使用新的syncword。
接收机在使用新的syncword后，如果发现超过5秒未收到任何数据包，则回到默认的syncword
*/
//在未match的时候，在初始化状态时就已经初始化了默认的通讯通道值,所以不用重复设置
unsigned char bsf_matchDo()
{

    //设置通道为0
    //匹配状态默认同步包
    if (bsf_itf_isRecvArrival() > 0)
    {
        ii = bsf_itf_recv(((unsigned char *)&IntlPayload) + 1, sizeof(BSF_Payload));
        IntlPayload.len = ii;
        if (ii < 3)
        {
            bsf_debug("[BSF] [MATCH] not a valid packet,size error.\r\n");
            //包有问题，不做判断
        }
        //else if (IntlPayload.ID == 0x0000)
        else if (BSF_IS_ID_ZERO(IntlPayload) && BSF_TYPE(IntlPayload) == BSF_TYPE_SYNC_PACK)
        {
            //阶段1，接收机收到了请求UUID指令，回复一个UUID

            bsf_debug("[BSF] [MATCH] New Transmitter Got.\r\n");
            IntlPayload.len = 3;
            //IntlPayload.ID = StorageInfo.ID;
            BSF_SET_ID_CPY(IntlPayload, StorageInfo);
            BSF_TYPE_SET(IntlPayload, BSF_TYPE_SYNC_PACK);
            BSF_BURNOUTSET(IntlPayload, Timer.BurnOutTimestampSec);
            bsf_itf_send(((unsigned char *)&IntlPayload) + 1, IntlPayload.len);
            bsf_itf_setToRx();
            //收到一个ID后，就启动定时器，避免ID占据太久
            isCountDownResetEnable = BSF_TRUE;
            TimerEnable = BSF_FALSE;
            BSF_SET_TIMER(Timer, SyncTimestampSec, MATCH_TIMEOUT);
            TimerEnable = BSF_TRUE;
        }
        //else if (StorageInfo.ID == IntlPayload.ID)
        else if (BSF_IS_ID_MATCH(StorageInfo, IntlPayload) && BSF_TYPE(IntlPayload) == BSF_TYPE_SYNC_PACK)
        {
            if (isOriginSync)
            {
                isOriginSync = BSF_FALSE;
                //阶段2，接收机看到UUID一样，发送UUID后切到新同步字等待
                bsf_debug("[BSF] [MATCH] OK,jump to new sync.\r\n");

                //发送需要的ID号
                IntlPayload.len = 3;
                //IntlPayload.ID = StorageInfo.ID;
                BSF_SET_ID_CPY(IntlPayload, StorageInfo);
                BSF_TYPE_SET(IntlPayload, BSF_TYPE_SYNC_PACK);
                BSF_BURNOUTSET(IntlPayload, Timer.BurnOutTimestampSec);
                bsf_itf_send(((unsigned char *)&IntlPayload) + 1, IntlPayload.len);
                bsf_itf_setSync(StorageInfo.ID);
                bsf_itf_setToRx();
                //收到ID后就开始倒计时5秒
                isCountDownResetEnable = BSF_TRUE;
                TimerEnable = BSF_FALSE;
                BSF_SET_TIMER(Timer, SyncTimestampSec, MATCH_TIMEOUT);
                TimerEnable = BSF_TRUE;
            }
            else
            {
                bsf_debug("[BSF] [MATCH] hit! sync success!\r\n");
                StorageInfo.match = BSF_MATCH;
                bsf_itf_save(0, (unsigned char *)&StorageInfo, sizeof(BSF_Storage));

                IntlPayload.len = 3;
                //IntlPayload.ID = StorageInfo.ID;
                BSF_SET_ID_CPY(IntlPayload, StorageInfo);
                BSF_TYPE_SET(IntlPayload, BSF_TYPE_SYNC_PACK);
                BSF_BURNOUTSET(IntlPayload, Timer.BurnOutTimestampSec);
                bsf_itf_send(((unsigned char *)&IntlPayload) + 1, IntlPayload.len);
                bsf_itf_setToRx();

                return BSF_TRUE;
            }
        }
    }

    if (Timer.SyncTimestampSec == 0 && isCountDownResetEnable == BSF_TRUE)
    {
        isCountDownResetEnable = BSF_FALSE;
        bsf_debug("[BSF] [MATCH] new channel set failed!\r\n");
        isOriginSync = BSF_TRUE;
        bsf_itf_setSyncDefault();
        bsf_itf_setToRx();
    }

    return BSF_FALSE;
}

unsigned char bsf_match()
{

    unsigned char ret = 0;

    if (MatchOnBoot == BSF_TRUE)
    {

        ret = bsf_matchDo();

        if (ret == BSF_TRUE)
        {
            MatchOnBoot = BSF_FALSE;
            return BSF_TRUE;
        }

        //时间耗尽后，不再进入MatchOnBoot,同时，检查下是否历史上已经match了
        if (Timer.SyncOnBootJobSec == 0)
        {
            MatchOnBoot = BSF_FALSE;
            if (StorageInfo.match == BSF_MATCH)
            {
                bsf_itf_setSync(StorageInfo.ID);
                bsf_itf_setToRx();
                bsf_debug("[BSF] [MATCH]On boot match no device,This is a paired device.Normal starting.\r\n");
                return BSF_TRUE;
            }
            bsf_debug("[BSF] [MATCH] On boot match no device,This is a brand new device.Keeping waiting for matching device.\r\n");
            return BSF_FALSE;
        }
    }

    if (StorageInfo.match == BSF_MATCH)
    {
        return BSF_TRUE;
    }
    else
    {
        return bsf_matchDo();
    }
}

unsigned char bsf_do(void)
{
    static unsigned char ConnCnt = 0;
    if (bsf_match() != BSF_TRUE)
    {
        return BSF_FALSE; //当设备未匹配时，任何其余逻辑都不将执行,bsf_do将直接返回
    }

    /*监听数据包，并根据数据包的内容进行存储，跳频老化,及跳频工作*/
    if (bsf_itf_isRecvArrival() > 0)
    {
        ii = bsf_itf_recv(((unsigned char *)&IntlPayload) + 1, sizeof(BSF_Payload));
        IntlPayload.len = ii;
        if (bsf_isIdMatch())
        {

            switch (BSF_TYPE(IntlPayload))
            {
            case BSF_TYPE_EMPTY_PACK:
                bsf_sendPack();
                //bsf_debug("[R] EMPTYPACK WITH RET\r\n");
                bsf_itf_setToRx();
                break;
            case BSF_TYPE_PAYLOAD_NORET:
                isAlive = 1;
                aliveCount = 1000;
                //这里将payload直接拷贝至缓存
                if (RecvPayload.len == 0)
                {
                    for (ii = 0; ii < sizeof(BSF_Payload); ii++)
                    {
                        ((unsigned char *)&RecvPayload)[ii] = ((unsigned char *)&IntlPayload)[ii];
                    }
                }
                //bsf_debug("[BSF] [MATCH] PAYLOAD WITH NO RET.\r\n");
                break;
            case BSF_TYPE_PAYLOAD_RET:
                isAlive = 1;
                aliveCount = 1000;
                bsf_sendPack();
                bsf_itf_setToRx();
                //发射机在收到payload时，不会管是否是需要返回的
                //这里将payload直接拷贝至缓存
                if (RecvPayload.len == 0)
                {
                    for (ii = 0; ii < sizeof(BSF_Payload); ii++)
                    {
                        ((unsigned char *)&RecvPayload)[ii] = ((unsigned char *)&IntlPayload)[ii];
                    }
                }
                //bsf_debug("[BSF] [MATCH]  PAYLOAD WITH RET.\r\n");
                break;
            default:
                break;
            }

            //当ID成功匹配时，将重置各个计数器值
            TimerEnable = BSF_FALSE;
            BSF_RESET_TIMER(Timer, LossTimestamp); //丢失计数器因为收到了有效的包，这里会清零
            TimerEnable = BSF_TRUE;

            //连接确认必须连续三次以上获得握手包
            if (ConnCnt > 3)
            {
                IsConnectLost = BSF_FALSE; //收到包意味着连接没有丢失
            }
            else
            {
                ConnCnt++;
            }
        }
        else
        {
            if (bsf_isRecvPaloadNewer() == BSF_FALSE)
            {
                TimerEnable = BSF_FALSE;
                BSF_RESET_TIMER(Timer, LossTimestamp); //丢失连接计数器也要重置为0
                BSF_SET_TIMER(Timer, BurnOutTimestampSec, BSF_BURNOUT_MAX);
                TimerEnable = BSF_TRUE;
                ConnCnt = 0;
                IsConnectLost = BSF_TRUE; //跳频必定意味着连接丢失

                bsf_setNextChannel();
                bsf_debug("[BSF] [MATCH] burnout freq jump.\r\n");
                //bsf_itf_setToRx();
            }
            else
            {
                //do nothing
            }
        }
    }

    //超时以后，进入下一个频率
    if (Timer.LossTimestamp > CONNECT_TIME_THRESHOLD)
    {
        //bsf_debug("[R] not connect freq jump\r\n");
        ConnCnt = 0;
        IsConnectLost = BSF_TRUE;

        TimerEnable = BSF_FALSE;
        BSF_RESET_TIMER(Timer, LossTimestamp);
        BSF_SET_TIMER(Timer, BurnOutTimestampSec, BSF_BURNOUT_MAX);
        TimerEnable = BSF_TRUE;
        bsf_setNextChannel();
        bsf_itf_setToRx();
    }

    return BSF_TRUE;
}
unsigned char bsf_isLinkEstablished(void)
{
    return !IsConnectLost;
}

unsigned char bsf_isAlive(void)
{
    return isAlive;
}
unsigned char bsf_isSendBufFree(void)
{
    if (SendPayload.len != 0)
    {
        return BSF_FALSE;
    }
    else
    {
        return BSF_TRUE;
    }
}

unsigned char bsf_isRecvBufNE(void)
{
    if (RecvPayload.len != 0)
    {
        return BSF_TRUE;
    }
    else
    {
        return BSF_FALSE;
    }
}

unsigned char *bsf_recvBegin(unsigned char *outLen)
{
    *outLen = RecvPayload.len - 3;
    return RecvPayload.buf;
}

void bsf_recvEnd(unsigned char isRecvOk)
{
    if (isRecvOk != BSF_FALSE)
    {
        RecvPayload.len = 0;
    }
}

unsigned char *bsf_sendBegin()
{
    return SendPayload.buf;
}

void bsf_sendEnd(unsigned char len)
{
    if (len == 0)
    {
        return;
    }
    else
    {
        SendPayload.len = len + 3;
    }
}
/*查看设备是否配对*/
unsigned char bsf_isPaired(void)
{
    if ((StorageInfo.match == BSF_MATCH) && (MatchOnBoot == BSF_FALSE))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/*定时器每ms执行的活儿*/
void bsf_timerPerMsDo(void)
{
    static unsigned int ms1000 = 0;
    if (TimerEnable == BSF_TRUE)
    {
        Timer.LossTimestamp++;
        Timer.RecvSendTimestamp++;
        ms1000++;
        if (ms1000 >= 1000)
        {
            ms1000 = 0;
            if (Timer.BurnOutTimestampSec != 0)
            {
                Timer.BurnOutTimestampSec--;
            }
            if (Timer.SyncTimestampSec != 0)
            {
                Timer.SyncTimestampSec--;
            }
            if (Timer.SyncOnBootJobSec != 0)
            {
                Timer.SyncOnBootJobSec--;
            }
        }
    }
    aliveCount--;
    if (aliveCount == 0)
    {
        isAlive = 0;
    }
}
#endif
